home *** CD-ROM | disk | FTP | other *** search
/ The Complete Utilities To…ka 501 Killer Utilities! / 501 Killer Utilities! (Macworld July 1995).cdr / Programming / OutOfPhase1.1 Source / OutOfPhase Folder / ASTExpression.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  20.5 KB  |  700 lines  |  [TEXT/KAHL]

  1. /* ASTExpression.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "ASTExpression.h"
  31. #include "TrashTracker.h"
  32. #include "Memory.h"
  33. #include "ASTArrayDeclaration.h"
  34. #include "ASTAssignment.h"
  35. #include "ASTBinaryOperator.h"
  36. #include "ASTConditional.h"
  37. #include "ASTExpressionList.h"
  38. #include "ASTFuncCall.h"
  39. #include "ASTLoop.h"
  40. #include "ASTOperand.h"
  41. #include "ASTUnaryOperator.h"
  42. #include "ASTVariableDeclaration.h"
  43. #include "ASTErrorForm.h"
  44. #include "ASTWaveGetter.h"
  45. #include "ASTPrintString.h"
  46. #include "ASTPrintExpr.h"
  47. #include "SymbolTableEntry.h"
  48.  
  49.  
  50. struct ASTExpressionRec
  51.     {
  52.         ExprTypes                        ElementType;
  53.         DataTypes                        WhatIsTheExpressionType;
  54.         long                                LineNumber;
  55.         union
  56.             {
  57.                 ASTArrayDeclRec*        ArrayDeclaration;
  58.                 ASTAssignRec*                Assignment;
  59.                 ASTBinaryOpRec*            BinaryOperator;
  60.                 ASTCondRec*                    Conditional;
  61.                 ASTExprListRec*            ExpressionList;
  62.                 ASTFuncCallRec*            FunctionCall;
  63.                 ASTLoopRec*                    Loop;
  64.                 ASTOperandRec*            Operand;
  65.                 ASTUnaryOpRec*            UnaryOperator;
  66.                 ASTVarDeclRec*            VariableDeclaration;
  67.                 ASTErrorFormRec*        ErrorForm;
  68.                 ASTWaveGetterRec*        WaveGetter;
  69.                 ASTPrintStringRec*    PrintString;
  70.                 ASTPrintExprRec*        PrintExpr;
  71.             } u;
  72.     };
  73.  
  74.  
  75. /* construct a generic expression around an array declaration */
  76. ASTExpressionRec*        NewExprArrayDecl(struct ASTArrayDeclRec* TheArrayDeclaration,
  77.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  78.     {
  79.         ASTExpressionRec*    Expr;
  80.  
  81.         CheckPtrExistence(TheArrayDeclaration);
  82.         CheckPtrExistence(TrashTracker);
  83.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  84.         if (Expr == NIL)
  85.             {
  86.                 return NIL;
  87.             }
  88.         SetTag(Expr,"ASTExpressionRec: NewExprArrayDecl");
  89.  
  90.         Expr->ElementType = eExprArrayDeclaration;
  91.         Expr->u.ArrayDeclaration = TheArrayDeclaration;
  92.         Expr->LineNumber = TheLineNumber;
  93.  
  94.         return Expr;
  95.     }
  96.  
  97.  
  98. /* construct a generic expression around an assignment statement */
  99. ASTExpressionRec*        NewExprAssignment(struct ASTAssignRec* TheAssignment,
  100.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  101.     {
  102.         ASTExpressionRec*    Expr;
  103.  
  104.         CheckPtrExistence(TheAssignment);
  105.         CheckPtrExistence(TrashTracker);
  106.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  107.         if (Expr == NIL)
  108.             {
  109.                 return NIL;
  110.             }
  111.         SetTag(Expr,"ASTExpressionRec: NewExprAssignment");
  112.  
  113.         Expr->ElementType = eExprAssignment;
  114.         Expr->u.Assignment = TheAssignment;
  115.         Expr->LineNumber = TheLineNumber;
  116.  
  117.         return Expr;
  118.     }
  119.  
  120.  
  121. /* construct a generic expression around a binary operator */
  122. ASTExpressionRec*        NewExprBinaryOperator(struct ASTBinaryOpRec* TheBinaryOperator,
  123.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  124.     {
  125.         ASTExpressionRec*    Expr;
  126.  
  127.         CheckPtrExistence(TheBinaryOperator);
  128.         CheckPtrExistence(TrashTracker);
  129.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  130.         if (Expr == NIL)
  131.             {
  132.                 return NIL;
  133.             }
  134.         SetTag(Expr,"ASTExpressionRec: NewExprBinaryOperator");
  135.  
  136.         Expr->ElementType = eExprBinaryOperator;
  137.         Expr->u.BinaryOperator = TheBinaryOperator;
  138.         Expr->LineNumber = TheLineNumber;
  139.  
  140.         return Expr;
  141.     }
  142.  
  143.  
  144. /* construct a generic expression around a conditional. */
  145. ASTExpressionRec*        NewExprConditional(struct ASTCondRec* TheConditional,
  146.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  147.     {
  148.         ASTExpressionRec*    Expr;
  149.  
  150.         CheckPtrExistence(TheConditional);
  151.         CheckPtrExistence(TrashTracker);
  152.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  153.         if (Expr == NIL)
  154.             {
  155.                 return NIL;
  156.             }
  157.         SetTag(Expr,"ASTExpressionRec: NewExprConditional");
  158.  
  159.         Expr->ElementType = eExprConditional;
  160.         Expr->u.Conditional = TheConditional;
  161.         Expr->LineNumber = TheLineNumber;
  162.  
  163.         return Expr;
  164.     }
  165.  
  166.  
  167. /* construct a generic expression around a list of expressions. */
  168. ASTExpressionRec*        NewExprSequence(struct ASTExprListRec* TheExpressionList,
  169.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  170.     {
  171.         ASTExpressionRec*    Expr;
  172.  
  173.         if (TheExpressionList != NIL)
  174.             {
  175.                 CheckPtrExistence(TheExpressionList);
  176.             }
  177.         CheckPtrExistence(TrashTracker);
  178.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  179.         if (Expr == NIL)
  180.             {
  181.                 return NIL;
  182.             }
  183.         SetTag(Expr,"ASTExpressionRec: NewExprSequence");
  184.  
  185.         Expr->ElementType = eExprExpressionList;
  186.         Expr->u.ExpressionList = TheExpressionList;
  187.         Expr->LineNumber = TheLineNumber;
  188.  
  189.         return Expr;
  190.     }
  191.  
  192.  
  193. /* construct a generic expression around a function call */
  194. ASTExpressionRec*        NewExprFunctionCall(struct ASTFuncCallRec* TheFunctionCall,
  195.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  196.     {
  197.         ASTExpressionRec*    Expr;
  198.  
  199.         CheckPtrExistence(TheFunctionCall);
  200.         CheckPtrExistence(TrashTracker);
  201.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  202.         if (Expr == NIL)
  203.             {
  204.                 return NIL;
  205.             }
  206.         SetTag(Expr,"ASTExpressionRec: NewExprFunctionCall");
  207.  
  208.         Expr->ElementType = eExprFunctionCall;
  209.         Expr->u.FunctionCall = TheFunctionCall;
  210.         Expr->LineNumber = TheLineNumber;
  211.  
  212.         return Expr;
  213.     }
  214.  
  215.  
  216. /* construct a generic expression around a loop */
  217. ASTExpressionRec*        NewExprLoop(struct ASTLoopRec* TheLoop,
  218.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  219.     {
  220.         ASTExpressionRec*    Expr;
  221.  
  222.         CheckPtrExistence(TheLoop);
  223.         CheckPtrExistence(TrashTracker);
  224.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  225.         if (Expr == NIL)
  226.             {
  227.                 return NIL;
  228.             }
  229.         SetTag(Expr,"ASTExpressionRec: NewExprLoop");
  230.  
  231.         Expr->ElementType = eExprLoop;
  232.         Expr->u.Loop = TheLoop;
  233.         Expr->LineNumber = TheLineNumber;
  234.  
  235.         return Expr;
  236.     }
  237.  
  238.  
  239. /* construct a generic expression around an operand */
  240. ASTExpressionRec*        NewExprOperand(struct ASTOperandRec* TheOperand,
  241.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  242.     {
  243.         ASTExpressionRec*    Expr;
  244.  
  245.         CheckPtrExistence(TheOperand);
  246.         CheckPtrExistence(TrashTracker);
  247.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  248.         if (Expr == NIL)
  249.             {
  250.                 return NIL;
  251.             }
  252.         SetTag(Expr,"ASTExpressionRec: NewExprOperand");
  253.  
  254.         Expr->ElementType = eExprOperand;
  255.         Expr->u.Operand = TheOperand;
  256.         Expr->LineNumber = TheLineNumber;
  257.  
  258.         return Expr;
  259.     }
  260.  
  261.  
  262. /* construct a generic expression around a unary operator */
  263. ASTExpressionRec*        NewExprUnaryOperator(struct ASTUnaryOpRec* TheUnaryOperator,
  264.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  265.     {
  266.         ASTExpressionRec*    Expr;
  267.  
  268.         CheckPtrExistence(TheUnaryOperator);
  269.         CheckPtrExistence(TrashTracker);
  270.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  271.         if (Expr == NIL)
  272.             {
  273.                 return NIL;
  274.             }
  275.         SetTag(Expr,"ASTExpressionRec: NewExprUnaryOperator");
  276.  
  277.         Expr->ElementType = eExprUnaryOperator;
  278.         Expr->u.UnaryOperator = TheUnaryOperator;
  279.         Expr->LineNumber = TheLineNumber;
  280.  
  281.         return Expr;
  282.     }
  283.  
  284.  
  285. /* construct a generic expression around a variable declaration */
  286. ASTExpressionRec*        NewExprVariableDeclaration(struct ASTVarDeclRec* TheVariableDecl,
  287.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  288.     {
  289.         ASTExpressionRec*    Expr;
  290.  
  291.         CheckPtrExistence(TheVariableDecl);
  292.         CheckPtrExistence(TrashTracker);
  293.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  294.         if (Expr == NIL)
  295.             {
  296.                 return NIL;
  297.             }
  298.         SetTag(Expr,"ASTExpressionRec: NewExprVariableDeclaration");
  299.  
  300.         Expr->ElementType = eExprVariableDeclaration;
  301.         Expr->u.VariableDeclaration = TheVariableDecl;
  302.         Expr->LineNumber = TheLineNumber;
  303.  
  304.         return Expr;
  305.     }
  306.  
  307.  
  308. /* construct a generic expression around an error form */
  309. ASTExpressionRec*        NewExprErrorForm(struct ASTErrorFormRec* TheErrorForm,
  310.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  311.     {
  312.         ASTExpressionRec*    Expr;
  313.  
  314.         CheckPtrExistence(TheErrorForm);
  315.         CheckPtrExistence(TrashTracker);
  316.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  317.         if (Expr == NIL)
  318.             {
  319.                 return NIL;
  320.             }
  321.         SetTag(Expr,"ASTExpressionRec: NewExprErrorForm");
  322.  
  323.         Expr->ElementType = eExprErrorForm;
  324.         Expr->u.ErrorForm = TheErrorForm;
  325.         Expr->LineNumber = TheLineNumber;
  326.  
  327.         return Expr;
  328.     }
  329.  
  330.  
  331. /* construct a generic expression around a wave getter */
  332. ASTExpressionRec*        NewExprWaveGetter(struct ASTWaveGetterRec* TheWaveGetter,
  333.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  334.     {
  335.         ASTExpressionRec*    Expr;
  336.  
  337.         CheckPtrExistence(TheWaveGetter);
  338.         CheckPtrExistence(TrashTracker);
  339.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  340.         if (Expr == NIL)
  341.             {
  342.                 return NIL;
  343.             }
  344.         SetTag(Expr,"ASTExpressionRec: NewExprWaveGetter");
  345.  
  346.         Expr->ElementType = eExprWaveGetter;
  347.         Expr->u.WaveGetter = TheWaveGetter;
  348.         Expr->LineNumber = TheLineNumber;
  349.  
  350.         return Expr;
  351.     }
  352.  
  353.  
  354. /* construct a generic expression around an error form */
  355. ASTExpressionRec*        NewExprPrintString(struct ASTPrintStringRec* ThePrintString,
  356.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  357.     {
  358.         ASTExpressionRec*    Expr;
  359.  
  360.         CheckPtrExistence(ThePrintString);
  361.         CheckPtrExistence(TrashTracker);
  362.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  363.         if (Expr == NIL)
  364.             {
  365.                 return NIL;
  366.             }
  367.         SetTag(Expr,"ASTExpressionRec: NewExprPrintString");
  368.  
  369.         Expr->ElementType = eExprPrintString;
  370.         Expr->u.PrintString = ThePrintString;
  371.         Expr->LineNumber = TheLineNumber;
  372.  
  373.         return Expr;
  374.     }
  375.  
  376.  
  377. /* construct a generic expression around an error form */
  378. ASTExpressionRec*        NewExprPrintExpr(struct ASTPrintExprRec* ThePrintExpr,
  379.                                             struct TrashTrackRec* TrashTracker, long TheLineNumber)
  380.     {
  381.         ASTExpressionRec*    Expr;
  382.  
  383.         CheckPtrExistence(ThePrintExpr);
  384.         CheckPtrExistence(TrashTracker);
  385.         Expr = (ASTExpressionRec*)AllocTrackedBlock(sizeof(ASTExpressionRec),TrashTracker);
  386.         if (Expr == NIL)
  387.             {
  388.                 return NIL;
  389.             }
  390.         SetTag(Expr,"ASTExpressionRec: NewExprPrintExpr");
  391.  
  392.         Expr->ElementType = eExprPrintExpr;
  393.         Expr->u.PrintExpr = ThePrintExpr;
  394.         Expr->LineNumber = TheLineNumber;
  395.  
  396.         return Expr;
  397.     }
  398.  
  399.  
  400. /* type check an expression.  returns eCompileNoError and the resulting value */
  401. /* type if it checks correctly. */
  402. CompileErrors                TypeCheckExpression(DataTypes* ResultTypeOut,
  403.                                             ASTExpressionRec* TheExpression, long* ErrorLineNumber,
  404.                                             struct TrashTrackRec* TrashTracker)
  405.     {
  406.         CompileErrors            ReturnValue;
  407.  
  408.         CheckPtrExistence(TheExpression);
  409.         CheckPtrExistence(TrashTracker);
  410.  
  411.         switch (TheExpression->ElementType)
  412.             {
  413.                 default:
  414.                     EXECUTE(PRERR(ForceAbort,"TypeCheckExpression:  unknown AST node type"));
  415.                     break;
  416.                 case eExprArrayDeclaration:
  417.                     ReturnValue = TypeCheckArrayConstruction(ResultTypeOut,
  418.                         TheExpression->u.ArrayDeclaration,ErrorLineNumber,TrashTracker);
  419.                     break;
  420.                 case eExprAssignment:
  421.                     ReturnValue = TypeCheckAssignment(ResultTypeOut,TheExpression->u.Assignment,
  422.                         ErrorLineNumber,TrashTracker);
  423.                     break;
  424.                 case eExprBinaryOperator:
  425.                     ReturnValue = TypeCheckBinaryOperator(ResultTypeOut,
  426.                         TheExpression->u.BinaryOperator,ErrorLineNumber,TrashTracker);
  427.                     break;
  428.                 case eExprConditional:
  429.                     ReturnValue = TypeCheckConditional(ResultTypeOut,TheExpression->u.Conditional,
  430.                         ErrorLineNumber,TrashTracker);
  431.                     break;
  432.                 case eExprExpressionList:
  433.                     /* this needs to be done specially */
  434.                     if (TheExpression->u.ExpressionList == NIL)
  435.                         {
  436.                             *ErrorLineNumber = TheExpression->LineNumber;
  437.                             ReturnValue = eCompileVoidExpressionIsNotAllowed;
  438.                         }
  439.                      else
  440.                         {
  441.                             ReturnValue = TypeCheckExprList(ResultTypeOut,
  442.                                 TheExpression->u.ExpressionList,ErrorLineNumber,TrashTracker);
  443.                         }
  444.                     break;
  445.                 case eExprFunctionCall:
  446.                     ReturnValue = TypeCheckFunctionCall(ResultTypeOut,TheExpression->u.FunctionCall,
  447.                         ErrorLineNumber,TrashTracker);
  448.                     break;
  449.                 case eExprLoop:
  450.                     ReturnValue = TypeCheckLoop(ResultTypeOut,TheExpression->u.Loop,ErrorLineNumber,
  451.                         TrashTracker);
  452.                     break;
  453.                 case eExprOperand:
  454.                     ReturnValue = TypeCheckOperand(ResultTypeOut,TheExpression->u.Operand,
  455.                         ErrorLineNumber,TrashTracker);
  456.                     break;
  457.                 case eExprUnaryOperator:
  458.                     ReturnValue = TypeCheckUnaryOperator(ResultTypeOut,
  459.                         TheExpression->u.UnaryOperator,ErrorLineNumber,TrashTracker);
  460.                     break;
  461.                 case eExprVariableDeclaration:
  462.                     ReturnValue = TypeCheckVariableDeclaration(ResultTypeOut,
  463.                         TheExpression->u.VariableDeclaration,ErrorLineNumber,TrashTracker);
  464.                     break;
  465.                 case eExprErrorForm:
  466.                     ReturnValue = TypeCheckErrorForm(ResultTypeOut,TheExpression->u.ErrorForm,
  467.                         ErrorLineNumber,TrashTracker);
  468.                     break;
  469.                 case eExprWaveGetter:
  470.                     ReturnValue = TypeCheckWaveGetter(ResultTypeOut,TheExpression->u.WaveGetter,
  471.                         ErrorLineNumber,TrashTracker);
  472.                     break;
  473.                 case eExprPrintString:
  474.                     ReturnValue = TypeCheckPrintString(ResultTypeOut,TheExpression->u.PrintString,
  475.                         ErrorLineNumber,TrashTracker);
  476.                     break;
  477.                 case eExprPrintExpr:
  478.                     ReturnValue = TypeCheckPrintExpr(ResultTypeOut,TheExpression->u.PrintExpr,
  479.                         ErrorLineNumber,TrashTracker);
  480.                     break;
  481.             }
  482.  
  483.         TheExpression->WhatIsTheExpressionType = *ResultTypeOut;
  484.         return ReturnValue;
  485.     }
  486.  
  487.  
  488. /* get a symbol table entry out of an expression.  this is used for getting */
  489. /* function generation stuff. */
  490. CompileErrors                ExpressionGetFunctionCallSymbol(struct SymbolRec** SymbolOut,
  491.                                             ASTExpressionRec* TheExpression)
  492.     {
  493.         SymbolRec*                FunctionThing;
  494.  
  495.         CheckPtrExistence(TheExpression);
  496.         if (TheExpression->ElementType != eExprOperand)
  497.             {
  498.                 return eCompileFunctionIdentifierRequired;
  499.             }
  500.         if (!IsOperandASymbol(TheExpression->u.Operand))
  501.             {
  502.                 return eCompileFunctionIdentifierRequired;
  503.             }
  504.         FunctionThing = GetSymbolFromOperand(TheExpression->u.Operand);
  505.         CheckPtrExistence(FunctionThing);
  506.         if (eSymbolFunction != WhatIsThisSymbol(FunctionThing))
  507.             {
  508.                 return eCompileFunctionIdentifierRequired;
  509.             }
  510.         *SymbolOut = FunctionThing;
  511.         return eCompileNoError;
  512.     }
  513.  
  514.  
  515. /* find out if the expression is a valid lvalue */
  516. MyBoolean                        IsExpressionValidLValue(ASTExpressionRec* TheExpression)
  517.     {
  518.         CheckPtrExistence(TheExpression);
  519.  
  520.         /* to be a valid lvalue, the expression must be one of */
  521.         /*  - variable */
  522.         /*  - array subscription operation */
  523.         switch (TheExpression->ElementType)
  524.             {
  525.                 default:
  526.                     return False;
  527.  
  528.                 case eExprBinaryOperator:
  529.                     return (BinaryOperatorWhichOne(TheExpression->u.BinaryOperator)
  530.                         == eBinaryArraySubscripting);
  531.  
  532.                 case eExprOperand:
  533.                     if (IsOperandASymbol(TheExpression->u.Operand))
  534.                         {
  535.                             SymbolRec*            TheOperandThing;
  536.  
  537.                             TheOperandThing = GetSymbolFromOperand(TheExpression->u.Operand);
  538.                             return WhatIsThisSymbol(TheOperandThing) == eSymbolVariable;
  539.                         }
  540.                      else
  541.                         {
  542.                             return False;
  543.                         }
  544.             }
  545.         EXECUTE(PRERR(ForceAbort,"IsExpressionValidLValue:  control reached end"));
  546.     }
  547.  
  548.  
  549. /* find out what kind of expression it is */
  550. ExprTypes                        WhatKindOfExpressionIsThis(ASTExpressionRec* TheExpression)
  551.     {
  552.         CheckPtrExistence(TheExpression);
  553.         return TheExpression->ElementType;
  554.     }
  555.  
  556.  
  557. /* get the operand from the generic expression */
  558. struct ASTOperandRec*    GetOperandOutOfExpression(ASTExpressionRec* TheExpression)
  559.     {
  560.         CheckPtrExistence(TheExpression);
  561.         ERROR(TheExpression->ElementType != eExprOperand,PRERR(ForceAbort,
  562.             "GetOperandOutOfExpression:  expression isn't an operand"));
  563.         return TheExpression->u.Operand;
  564.     }
  565.  
  566.  
  567. /* get the binary operator out of the generic expression */
  568. struct ASTBinaryOpRec*    GetBinaryOperatorOutOfExpression(ASTExpressionRec* TheExpression)
  569.     {
  570.         CheckPtrExistence(TheExpression);
  571.         ERROR(TheExpression->ElementType != eExprBinaryOperator,PRERR(ForceAbort,
  572.             "GetBinaryOperatorOutOfExpression:  expression isn't an operand"));
  573.         return TheExpression->u.BinaryOperator;
  574.     }
  575.  
  576.  
  577. /* get the type of value that is returned by this expression */
  578. DataTypes                        GetExpressionsResultantType(ASTExpressionRec* TheExpression)
  579.     {
  580.         CheckPtrExistence(TheExpression);
  581.         return TheExpression->WhatIsTheExpressionType;
  582.     }
  583.  
  584.  
  585. /* generate code for an expression.  returns True if successful, or False if it fails. */
  586. MyBoolean                        CodeGenExpression(struct PcodeRec* FuncCode,
  587.                                             long* StackDepthParam, ASTExpressionRec* Expression)
  588.     {
  589.         long                            StackDepth;
  590.  
  591.         CheckPtrExistence(FuncCode);
  592.         CheckPtrExistence(Expression);
  593.         StackDepth = *StackDepthParam;
  594.  
  595.         switch (Expression->ElementType)
  596.             {
  597.                 default:
  598.                     EXECUTE(PRERR(ForceAbort,"CodeGenExpression:  unknown expression type"));
  599.                     break;
  600.                 case eExprArrayDeclaration:
  601.                     if (!CodeGenArrayConstruction(FuncCode,&StackDepth,
  602.                         Expression->u.ArrayDeclaration))
  603.                         {
  604.                             return False;
  605.                         }
  606.                     break;
  607.                 case eExprAssignment:
  608.                     if (!CodeGenAssignment(FuncCode,&StackDepth,Expression->u.Assignment))
  609.                         {
  610.                             return False;
  611.                         }
  612.                     break;
  613.                 case eExprBinaryOperator:
  614.                     if (!CodeGenBinaryOperator(FuncCode,&StackDepth,Expression->u.BinaryOperator))
  615.                         {
  616.                             return False;
  617.                         }
  618.                     break;
  619.                 case eExprConditional:
  620.                     if (!CodeGenConditional(FuncCode,&StackDepth,Expression->u.Conditional))
  621.                         {
  622.                             return False;
  623.                         }
  624.                     break;
  625.                 case eExprExpressionList:
  626.                     if (!CodeGenExpressionListSequence(FuncCode,&StackDepth,
  627.                         Expression->u.ExpressionList))
  628.                         {
  629.                             return False;
  630.                         }
  631.                     break;
  632.                 case eExprFunctionCall:
  633.                     if (!CodeGenFunctionCall(FuncCode,&StackDepth,Expression->u.FunctionCall))
  634.                         {
  635.                             return False;
  636.                         }
  637.                     break;
  638.                 case eExprLoop:
  639.                     if (!CodeGenLoop(FuncCode,&StackDepth,Expression->u.Loop))
  640.                         {
  641.                             return False;
  642.                         }
  643.                     break;
  644.                 case eExprOperand:
  645.                     if (!CodeGenOperand(FuncCode,&StackDepth,Expression->u.Operand))
  646.                         {
  647.                             return False;
  648.                         }
  649.                     break;
  650.                 case eExprUnaryOperator:
  651.                     if (!CodeGenUnaryOperator(FuncCode,&StackDepth,Expression->u.UnaryOperator))
  652.                         {
  653.                             return False;
  654.                         }
  655.                     break;
  656.                 case eExprVariableDeclaration:
  657.                     if (!CodeGenVarDecl(FuncCode,&StackDepth,Expression->u.VariableDeclaration))
  658.                         {
  659.                             return False;
  660.                         }
  661.                     break;
  662.                 case eExprErrorForm:
  663.                     if (!CodeGenErrorForm(FuncCode,&StackDepth,Expression->u.ErrorForm))
  664.                         {
  665.                             return False;
  666.                         }
  667.                     break;
  668.                 case eExprWaveGetter:
  669.                     if (!CodeGenWaveGetter(FuncCode,&StackDepth,Expression->u.WaveGetter))
  670.                         {
  671.                             return False;
  672.                         }
  673.                     break;
  674.                 case eExprPrintString:
  675.                     if (!CodeGenPrintString(FuncCode,&StackDepth,Expression->u.PrintString))
  676.                         {
  677.                             return False;
  678.                         }
  679.                     break;
  680.                 case eExprPrintExpr:
  681.                     if (!CodeGenPrintExpr(FuncCode,&StackDepth,Expression->u.PrintExpr))
  682.                         {
  683.                             return False;
  684.                         }
  685.                     break;
  686.             }
  687.         ERROR(
  688.             (((Expression->ElementType != eExprVariableDeclaration)
  689.                 && (Expression->ElementType != eExprArrayDeclaration))
  690.                 && (StackDepth != *StackDepthParam + 1))
  691.             ||
  692.             (((Expression->ElementType == eExprVariableDeclaration)
  693.                 || (Expression->ElementType == eExprArrayDeclaration))
  694.                 && (StackDepth != *StackDepthParam + 2)),
  695.             PRERR(ForceAbort,"CodeGenExpression:  stack depth error"));
  696.  
  697.         *StackDepthParam = StackDepth;
  698.         return True;
  699.     }
  700.